package com.sinosoft.brokerchannel.base.utile;

import com.sinosoft.brokerchannel.base.common.SystemParamFinal;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 公共工具类
 */
public class CommonUtil {
    // add by yangwentao reason:RM-3612 渠道平台新增时间戳日志-渠道平台   评审人:李振民  评审日期:2018-01-03 date：2017-12-28 begin
    public static final String REPEAT = "Repeat";
    private static final XStream xs = new XStream(new XppDriver(new Obj2Strings()));
    // add by yangwentao reason:RM-3612 渠道平台新增时间戳日志-渠道平台   评审人:李振民  评审日期:2018-01-03 date：2017-12-28 end
    protected static Logger logger = LoggerFactory.getLogger(CommonUtil.class);
    static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    public static String dto2xml(Object obj, Class... clazz) {
        if (null == obj && (null == clazz || 1 > clazz.length)) {
            return null;
        }
        xs.autodetectAnnotations(true);
        xs.processAnnotations(obj != null ? obj.getClass() : null);
        if (null != clazz && 0 < clazz.length) {
            xs.processAnnotations(clazz);
        }
        return xs.toXML(obj);
    }

    public static Object xml2dto(String xml, Class... clazz) {
        if (null == clazz || 1 > clazz.length) {
            return null;
        }
        XStream xs = new XStream(new StaxDriver());
        xs.autodetectAnnotations(true);
        xs.processAnnotations(clazz);
        return xs.fromXML(xml);
    }

    public static Object json2dto(String json, Class... clazz) {
        Object obj = null;
        if (null == clazz || 1 > clazz.length) {
            return null;
        }
        XStream xs = new XStream(new JettisonMappedXmlDriver());
        xs.autodetectAnnotations(true);
        xs.ignoreUnknownElements();
        xs.processAnnotations(clazz);
        obj = xs.fromXML(json);
        return obj;
    }

    /**
     * 字符串转换为日期
     *
     * @param str
     * @return
     * @throws ParseException
     */
    public static Date str2date(String str) throws ParseException {
        Date date = null;
        if (str == null || "".equals(str) || "null".equals(str)) {
            return null;
        } else if (str.matches("[12][0-9]{3}\\-[0-9]{1,2}\\-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}")) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(str);
        } else if (str.matches("[12][0-9]{12}")) {
            return new SimpleDateFormat("yyyyMMddHHmm").parse(str);
        } else if (str.indexOf("-") < 0) {
            if (str.length() >= 8) {
                str = str.substring(0, 8);
            }
            DateFormat dft = new SimpleDateFormat("yyyyMMdd");
            date = dft.parse(str);
            return date;
            //add by lizhenmin reason:支付时间修改 date:2017-11-15 begin
        } else if (null != str && str.matches("[12][0-9]{3}\\-[0-9]{1,2}\\-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}")) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(str);
            //add by lizhenmin reason:支付时间修改 date:2017-11-15 end
        } else {
            DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
            date = dft.parse(str);
            return date;
        }
    }

    /**
     * 字符串转换为日期
     * 1.精确到时分秒
     * 2.支持多种格式的转换
     *
     * @param str
     * @return Date
     * @throws Exception
     */
    //add by yangwentao SCM-299核心系统时间字段数据治理  date:2017-11-15 begin
    public static Date strToDate(String str) throws Exception {
        Date date = null;
        if (str == null || "".equals(str) || "null".equals(str)) {
            return null;
        } else if (str.matches("[12][0-9]{3}\\-[0-9]{1,2}\\-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}")) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(str);
        } else if (str.matches("[12][0-9]{12}")) {
            return new SimpleDateFormat("yyyyMMddHHmm").parse(str);
        } else if (str.indexOf("-") < 0) {
            if (str.length() > 8 && str.matches("[12][0-9]{13}")) {
                DateFormat dft = new SimpleDateFormat("yyyyMMddHHmmss");
                date = dft.parse(str);
                return date;
            }
            str = str.substring(0, 8);
            DateFormat dft = new SimpleDateFormat("yyyyMMdd");
            date = dft.parse(str);
            return date;
        } else if (str.matches("[12][0-9]{3}\\-[0-9]{1,2}\\-[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}")) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(str);
        } else {
            DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
            date = dft.parse(str);
            return date;
        }

    }

    //add by yangwentao SCM-299核心系统时间字段数据治理  date:2017-11-15 end
    public static void obj2str(Object obj) {
        try {
            logger.info(xs.toXML(obj));
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
        }
    }

    /**
     * 字符串转换为长整数
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static long str2long(String str) throws Exception {
        if (str != null && !"".equals(str) && !"null".equals(str)) {
            return Long.parseLong(str);
        } else {
            return 0;
        }
    }

    public static String timestamp2Str(Timestamp time) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time);
    }

    /**
     * 字符串转换成整数
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static int str2int(String str) throws Exception {
        if (!"".equals(str) && str != null && !"null".equals(str)) {
            return Integer.valueOf(str);
        } else {
            return 0;
        }
    }

    /**
     * 字符串转换成浮点数
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static double str2double(String str) throws Exception {
        if (!"".equals(str) && str != null && !"null".equals(str)) {
            return Double.valueOf(str);
        } else {
            return 0;
        }
    }

    /**
     * 日期转换成字符串类型
     *
     * @param date
     * @return
     */
    public static String date2Str_yyyyMMddHHmmss(Date date) throws BusinessException {
        try {//yyyy-MM-dd HH:mm:ss
            DateFormat dft = new SimpleDateFormat("yyyyMMddHHmmss");
            if (date != null) {
                String ss = dft.format(date);
                return ss;
            } else {
                return "";
            }
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            throw new BusinessException("CU-0000", "日期转换异常");
        }
    }
    /**
     * 日期转换成字符串类型
     *  yyyy-MM-dd
     * @param date
     * @return
     */
    public static String date2Str_yyyyMMdd(Date date) throws BusinessException {
        try {//yyyy-MM-dd HH:mm:ss
            DateFormat dft = new SimpleDateFormat("yyyy-MM-dd");
            if (date != null) {
                String ss = dft.format(date);
                return ss;
            } else {
                return "";
            }
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            throw new BusinessException("CU-0000", "日期转换异常");
        }
    }
    //yyyy-MM-dd HH:mm:ss
    public static String date2Str_yyyy_MM_dd_HHmmss(String string) throws BusinessException {
        try {
            Date now = null;
            if (string != null && !"null".equals(string)) {
                if (string.matches("\\d{14}")) {
                    now = new SimpleDateFormat("yyyyMMddHHmmss").parse(string);
                } else {
                    throw new BusinessException("00039","不支持的日期格式: " + string);
                }
                SimpleDateFormat dft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String ss = dft.format(now);
                return ss;
            } else {
                return "";
            }
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            throw new BusinessException("CU-0000", "日期转换异常");
        }
    }

    /**
     * 中文转码
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String urlEncoder(String str) throws Exception {
        try {
            if (str != null && !"".equals(str)) {
                return URLEncoder.encode(str, "utf-8");
            } else {
                return "";
            }

        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            throw e;
        }
    }

    /**
     * 中文解码
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String urlDecoder(String str) throws Exception {
        try {
            return URLDecoder.decode(str, "utf-8");
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            throw e;
        }
    }

    /**
     * 字符串转换为日期
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static Date str_yyyy_MM_dd_hhmmss_2date(String str) throws Exception {
        Date date = null;
        DateFormat dft = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (str == null || "".equals(str) && !"null".equals(str)) {
            return null;
        } else {
            date = dft.parse(str);
            return date;
        }
    }

    /**
     * 字符串转换为日期
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static Date str_yyyymmddhhmmss_2date(String str) throws Exception {
        Date date = null;
        DateFormat dft = new SimpleDateFormat("yyyyMMddHHmmss");
        if (str == null || "".equals(str) || "null".equals(str)) {
            return null;
        } else {
            date = dft.parse(str);
            return date;
        }
    }

    /**
     * 去除字符串末尾特殊字符
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String removeSpecialCharactersFromTheEndOfTheString(String str) {
        String returnStr = "";
        try {
            if (str.endsWith("&&")) {
                returnStr = str.substring(0, str.lastIndexOf("&&"));
            } else {
                returnStr = str;
            }
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
            returnStr = str;
        }
        return returnStr;
    }

    public static String double2str(Double d) throws Exception {
        if (d == null) {
            return "0";
        } else {
            return d.toString();
        }
    }

    public static void main(String[] args) {
        logger.info(removeSpecialCharactersFromTheEndOfTheString("hello&&"));
    }

    public static String sumDouble(Object... args) throws BusinessException {
        Double temp = new Double(0);
        try {
            for (int i = 0; null != args && i < args.length; i++) {
                if (null == args[i]) {
                } else if (args[i] instanceof String) {
                    temp += Double.valueOf((String) args[i]);
                } else if (args[i] instanceof Double) {
                    temp += (Double) args[i];
                }
            }
        } catch (Exception e) {
            throw new BusinessException("CommonUtil-0000", "参数求和失败");
        }
        return temp.toString();
    }

    public static String sumDouble(List<Object> a) throws BusinessException {
        Double temp = new Double(0);
        try {
            for (int i = 0; null != a && i < a.size(); i++) {
                if (null == a.get(i)) {
                } else if (a.get(i) instanceof String) {
                    temp += Double.valueOf((String) a.get(i));
                } else if (a.get(i) instanceof Double) {
                    temp += (Double) a.get(i);
                }
            }
        } catch (Exception e) {
            throw new BusinessException("CommonUtil-0001", "参数求和失败");
        }
        return temp.toString();
    }

    /**
     * double精度格式化
     *
     * @param b
     * @param scale
     * @return
     */
    public static BigDecimal round(BigDecimal b, int scale) {
        if (b == null) {
            b = BigDecimal.valueOf(0.00);
        }
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, 4);
    }

    /**
     * 日期格式化
     *
     * @param date
     * @return Calendar
     * @throws Exception
     */
    public static Date dateFormat(Date date) throws Exception {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (date != null) {
            date = df.parse(df.format(date));
        }
        return date;
    }

    static public void bytes2file(byte[] bytes, File file) {
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
            bos.flush();
        } catch (FileNotFoundException e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
        } catch (IOException e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
        } finally {
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.info(SystemParamFinal.Exception_LOG, e);
                }
            }
            if (null != bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    logger.info(SystemParamFinal.Exception_LOG, e);
                    ;
                }
            }
        }
    }

    static public byte[] file2bytes(String path) {
        return file2bytes(new File(path));
    }

    static public byte[] file2bytes(File file) {
        byte[] bytes = new byte[(int) file.length()];
        FileOutputStream fos = null;
        BufferedOutputStream bos = null;
        try {
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
            bos.flush();
        } catch (FileNotFoundException e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
        } catch (IOException e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
        } finally {
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    logger.info(SystemParamFinal.Exception_LOG, e);
                    ;
                }
            }
            if (null != bos) {
                try {
                    bos.close();
                } catch (IOException e) {
                    logger.info(SystemParamFinal.Exception_LOG, e);
                    ;
                }
            }
        }
        return bytes;
    }

    static public void print(String obj, String str, String channel) {
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        try {
            logger.info(str + " on " + now + " by " + channel + "  start");
            logger.info("------------------------------------------------------------------");
            logger.info(obj);
            logger.info("------------------------------------------------------------------");
            logger.info(str + " on " + now + " by " + channel + "  end");
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
        }
    }

    static public void print(Object obj, String str, String channel) {
        String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        try {
            logger.info(str + " on " + now + " by " + channel + "  start");
            logger.info("------------------------------------------------------------------");
            logger.info(dto2xml(obj));
            logger.info("------------------------------------------------------------------");
            logger.info(str + " on " + now + " by " + channel + "  end");
        } catch (Exception e) {
            logger.info(SystemParamFinal.Exception_LOG, e);
            ;
        }
    }

    /**
     * 统计生成保单调用各个接口方法耗时
     *
     * @param startSum 开始耗时时间戳
     * @param id       调用第三方接口唯一标识
     * @param map      存调用第三方的值
     */
    public static void timeLog(long startSum, String id, Map<Object, Object> map) {
        if (null != map) {
            boolean containsKey = map.containsKey(id);
            if (containsKey) {
                map.put(id + REPEAT, System.currentTimeMillis() - startSum);
            } else {
                map.put(id, System.currentTimeMillis() - startSum);
            }
        }
    }
    // add by yangwentao reason:RM-3612 渠道平台新增时间戳日志-渠道平台   评审人:李振民  评审日期:2018-01-03  date：2017-12-28 begin

    /**
     * 获取UUID
     *
     * @param id  调用第三方接口唯一标识
     * @param map 获取UUID
     */
    public static String printUUID(String id, Map<Object, Object> map) {
        if (null != map && map.get("uuid") != null) {
            return (String) map.get("uuid");
        } else {
            return "";
        }
    }

    // add by yangwentao reason:RM-3612 渠道平台新增时间戳日志-渠道平台   评审人:李振民  评审
    // add by yangwentao reason:RM-3914关系人名称校验规则-禁止录入符号-车险渠道  审人:李振民  评审时间:2018.01.15  date：2018-01-12 begin
    public static void checkSymbol(String name) throws BusinessException {
        if (name != null && !"".equals(name)) {
            if (name.contains("\\")) {
                throw new BusinessException("0062","0062");
            }
            String regEx = "[`~!@#$%&*()+=':;',《》<>/?~！@#￥%&*+{}‘；：’。，、？￥]";
            Pattern pattern = Pattern.compile(regEx);
            Matcher matcher = pattern.matcher(name);
            if (matcher.find()) {
                throw new BusinessException("0062","0062");
            }
        }

    }
    // add by yangwentao reason:RM-3914关系人名称校验规则-禁止录入符号-车险渠道 审人:李振民  评审时间:2018.01.15  date：2018-01-12 end

    static class Obj2Strings extends XmlFriendlyNameCoder {
        public Obj2Strings() {
            super("_-", "_");
        }
    }

}
